package com.cares.core.mng.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springside.modules.utils.DateProvider;

import com.cares.core.base.service.BaseService;
import com.cares.core.mng.repository.MenuMybatisDao;
import com.cares.core.mng.service.ShiroDbRealm.ShiroUser;
import com.cares.core.utils.Constant;
import com.cares.core.utils.StringUtil;
import com.cares.entity.mng.Menu;
import com.cares.entity.mng.MenuOperate;

/**
 * 更高效的AccountService实现，基于MyBatis + Memcached的方案，以JSON格式存储Memcached中的内容。
 * 
 * @author zhiweip
 */
@Service("menuService")
@Transactional(readOnly = true)
public class MenuService extends BaseService {
	
	private DateProvider dateProvider = DateProvider.DEFAULT;
	
	private static Logger logger = LoggerFactory.getLogger(MenuService.class);

	@Autowired
	private MenuMybatisDao menuDao;

	/**
	 * 先访问Memcached, 使用JSON字符串存放对象以节约空间.
	 */
	public Menu getMenu(Long id) {
		return menuDao.getMenu(id);
	}

	/**
	 * 主页面加载时查询菜单列表
	 * @param menu
	 * @return
	 */
	public List<Menu> searchMenu(Menu menu) {
		super.getCurrentUser().setMenuOpts(menuDao.getAllOptCodes());
		return menuDao.findMenuTree(menu);
	}

	/**
	 * 过滤菜单列表中没有子菜单的项
	 * 
	 * @param list
	 * @param mids
	 */
	private void Filter(List<Menu> list, List<Long> mids) {
		List<Menu> rsublist = null;
		List<Menu> mlist = new ArrayList<Menu>();
		for (Menu menu : list) {
			if (mids.contains(menu.getId()))
				continue;
			rsublist = new ArrayList<Menu>();
			for (Menu subm : menu.getSubMenuList()) {
				if (!mids.contains(subm.getId())) {
					rsublist.add(subm);
				}
			}
			menu.getSubMenuList().removeAll(rsublist);
			if (menu.getSubMenuList().size() == 0) {
				mlist.add(menu);
			}
		}
		list.removeAll(mlist);
	}

	/**
	 * 获取授权菜单列表
	 * @param menu
	 * @return
	 */
	public void searchAuthMenu(Menu menu) {
		ShiroUser suser = super.getCurrentUser();
		List<Map> rmap = menuDao.getUserMenuOpts(suser.getId());
		List<Long> mids = new ArrayList<Long>();
		StringBuffer fns = new StringBuffer("");
		for (Map item : rmap) {
			mids.add(Long.valueOf(item.get("menuId").toString()));
			fns.append(";" + item.get("func"));
		}
		List<Menu> list = searchMenu(menu);
		Filter(list, mids);
		String mfs = fns.toString();
		String[] aa = mfs.split(";");
		List<Long> optids = new ArrayList<Long>();
		for (String it : aa) {
			if (null != it && !"".equals(it) && !"null".equals(it)) {
				optids.add(Long.valueOf(it));
			}
		}
		if (optids.size() == 0)
			optids.add(0l);
		super.getCurrentUser().setMenuOpts(menuDao.getUserOptCodes(optids));
		Map result = new HashMap();
		menu.setSubMenuList(list);
	}

	/**
	 * 根据id、menuId、code查询菜单操作按钮信息
	 * @param param
	 * @return
	 */
	public List<MenuOperate> findMenuOperate(MenuOperate param) {
		return menuDao.findMenuOperate(param);
	}

	/**
	 * 更新菜单信息
	 * @param menu
	 */
	public void updateMenu(Menu menu) {
		Assert.notNull(menu.getId(), "缺少主键");

		menu.setUpdateUser(super.getCurrentUserName());
		menu.setUpdateTime(dateProvider.getDate());
		menuDao.updateMenu(menu);
	}

	/**
	 * 新增或修改菜单
	 * @param menu
	 */
	@Transactional(readOnly = false)
	public void saveOrUpdateMenu(Menu menu) {
		if ("1".equals(menu.getMenuLevel())) {
			menu.setUpMenuId(new Long(1));
		}

		if (StringUtil.isEmpty(menu.getIconCls())) {
			menu.setIconCls("menu-oprateMgr");
		}
		if (null != menu.getId()) {
			Menu dbMenu = getMenu(menu.getId());
			dbMenu.setMenuLevel(menu.getMenuLevel());
			dbMenu.setUpMenuId(menu.getUpMenuId());
			dbMenu.setName(menu.getName());
			dbMenu.setUrl(menu.getUrl());
			dbMenu.setIconCls(menu.getIconCls());
			dbMenu.setAvailable(menu.getAvailable());
			dbMenu.setMenuSort(menu.getMenuSort());
			dbMenu.setMenuPath(getMenuPath(menu.getUpMenuId()) + menu.getId() + ">>");
			dbMenu.setUpdateUser(getCurrentUserName());
			dbMenu.setUpdateTime(dateProvider.getDate());
			updateMenu(dbMenu);
		} else {
			if (null == menu.getUpMenuId())
				menu.setUpMenuId(new Long(1));
			//Long menuId = super.getTableKey("TS_MENU");

			//menu.setMenuPath(getMenuPath(menu.getUpMenuId()) + menuId + ">>");
			//menu.setId(menuId);

			menu.setCreateUser(super.getCurrentUserName());
			menu.setCreateTime(dateProvider.getDate());
			menu.setDelFlag("N");
			menu.setSysMenu("N");
			menuDao.saveMenu(menu);
			
			//更新menuPath
			menu.setMenuPath(getMenuPath(menu.getUpMenuId()) + menu.getId() + ">>");
			menu.setUpdateUser(getCurrentUserName());
			menu.setUpdateTime(dateProvider.getDate());
			updateMenu(menu);
		}
	}
	
	/**
	 * 新增或修改菜单操作按钮信息
	 * @param menu
	 */
	public void saveOrUpdateMenuOperate(MenuOperate menu) {
		Assert.notNull(menu.getMenuId(), "缺少主键");
		if (null != menu.getId()) {
			// XXX
		} else {
			menu.setCreateUser(super.getCurrentUserName());
			menu.setCreateTime(dateProvider.getDate());
			menuDao.saveOperate(menu);
		}
	}
	
	/**
	 * 删除菜单及子菜单
	 * @param id
	 */
	public void deleteMenu(Long id) {
		Menu param =menuDao.getMenu(id);
		if(null!=param && Constant.IS_N.equals(param.getDelFlag())){
			menuDao.deleteMenu(param);
		}
	}

	/**
	 * 根据上级菜单ID获取可用的菜单信息列表
	 * @param nodeId
	 * @return
	 */
	public List menuTopList(Long nodeId) {
		Menu param = new Menu();
		param.setUpMenuId(nodeId);
		param.setAvailable("Y");

		List<Menu> menuList = menuDao.findMenuTree(param);

		List<Map<String, Object>> itemsList = new ArrayList<Map<String, Object>>();
		for (Menu menu : menuList) {
			Map<String, Object> item = new HashMap<String, Object>();
			item.put("id", menu.getId());
			item.put("name", menu.getName());
			item.put("state", "open");
			item.put("iconCls", menu.getIconCls());
			item.put("url", menu.getUrl());
			item.put("upMenuId", menu.getUpMenuId());
			itemsList.add(item);
		}

		return itemsList;
	}
	
	/**
	 * 根据上级菜单ID获取菜单树
	 * @param nodeId
	 * @return
	 */
	public List menuTree(Long nodeId) {
		return menuTree(nodeId, 0);
	}
	
	/**
	 * 根据上级菜单ID和style获取菜单树
	 * @param nodeId 上级菜单ID
	 * @param style
	 * @return
	 */
	public List menuTree(Long nodeId, int style) {
		Menu menu = new Menu();
		menu.setUpMenuId(nodeId);
		List<Menu> list = menuDao.findMenuTree(menu);

		ShiroUser suser = super.getCurrentUser();
		if (!super.getCurrentUser().isSuperMan()) {
			List<Map> rmap = menuDao.getUserMenuOpts(suser.getId());
			List<Long> mids = new ArrayList<Long>();
			for (Map item : rmap) {
				mids.add(Long.valueOf(item.get("menuId").toString()));
			}
			Filter(list, mids);
		}
		return getAllMenuObject(list, style);
	}

	/**
	 * 根据menuList和style返回全部菜单(包括子菜单)结果List
	 * @param menuList
	 * @param style
	 * 		  0:获取菜单操作信息,例如删除、按钮设置
	 * 		  1:获取菜单操作按钮信息
	 */
	private List getAllMenuObject(List<Menu> menuList, int style) {

		List<Map<String, Object>> itemsList = new ArrayList<Map<String, Object>>();
		for (Menu menu : menuList) {
			Map<String, Object> item = new HashMap<String, Object>();
			item.put("id", menu.getId());
			item.put("name", menu.getName());
			item.put("text", menu.getName());
			item.put("state", "open");
			item.put("iconCls", menu.getIconCls());
			item.put("upMenuId", menu.getUpMenuId());
			item.put("iconCls", menu.getIconCls());
			item.put("children", getSubMenuObject(menu.getSubMenuList(), style));
			if (style == 0) {
				item.put("url", menu.getUrl());
				item.put("available", menu.getAvailable());
				item.put("menuSort", menu.getMenuSort());
				item.put("optBut", "[ <a href='#' onClick='editMenuBut("
						+ menu.getId() + ",\"DEL\")'>删除</a> ]");
			}
			itemsList.add(item);
		}

		return itemsList;
	}
	
	/**
	 * 根据子菜单menuList和style返回结果List
	 * @param menuList
	 * @param style
	 * 		  0:获取菜单操作信息,例如删除、按钮设置
	 * 		  1:获取菜单操作按钮信息
	 * @return
	 */
	private List getSubMenuObject(List<Menu> menuList, int style) {

		List<Map<String, Object>> itemsList = new ArrayList<Map<String, Object>>();
		for (Menu menu : menuList) {
			Map<String, Object> item = new HashMap<String, Object>();
			item.put("id", menu.getId());
			item.put("name", menu.getName());
			item.put("text", menu.getName());
			item.put("iconCls", menu.getIconCls());
			item.put("url", menu.getUrl());
			item.put("available", menu.getAvailable());
			item.put("iconCls", menu.getIconCls());
			item.put("state", "open");
			if (style == 0) {
				item.put("menuSort", menu.getMenuSort());
				item.put(
								"optBut",
								"[ <a href='#' onClick='editMenuBut("
										+ menu.getId()
										+ ",\"DEL\")'>删除</a> ] [ <a href='#' onClick='editMenuBut("
										+ menu.getId()
										+ ",\"VIEW\")'>按钮设置</a> ]");
			}
			if (style == 1)
				item.put("children", getMenuFuncObject(menu.getId()));
			itemsList.add(item);
		}

		return itemsList;
	}

	/**
	 * 根据menuId获取菜单操作按钮信息列表
	 * @param menuId
	 * @return
	 */
	private List getMenuFuncObject(Long menuId) {
		MenuOperate menu = new MenuOperate();
		menu.setMenuId(menuId);
		List<MenuOperate> funList = menuDao.findMenuOperate(menu);

		List<Map<String, Object>> itemsList = new ArrayList<Map<String, Object>>();
		for (MenuOperate func : funList) {
			Map<String, Object> item = new HashMap<String, Object>();
			item.put("id", func.getMenuId() + "-" + func.getId());
			item.put("text", func.getName() + "[" + func.getCode() + "]");
			item.put("state", "open");
			item.put("iconCls", "menu-moduleOp");
			itemsList.add(item);
		}

		return itemsList;
	}

	/**
	 * 根据menuId获取菜单路径
	 * 
	 * @param menuId
	 * @return
	 */
	public String getMenuPath(Long menuId) {
		Menu param = menuDao.getMenu(menuId);
		if (null==param) {
			return "1>>";
		}else if (param.getUpMenuId().intValue() == 0) {
			return param.getId() + ">>";
		} else {
			return getMenuPath(param.getUpMenuId()) + param.getId() + ">>";
		}

	}

	/**
	 * 根据id删除菜单操作按钮
	 * @param id
	 */
	public void deleteMenuOperate(Long id) {
		menuDao.deleteMenuOperate(id);
	}
}
